package cc.linker.steplink.crm.merchanth5.util;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @Author chenzhiqing
 * @Description
 * @Date 2017-09-24 9:05
 */
public class ParamSignUtils {
    public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {

        //定义封装参数的map,微信退款查询接口参数
        HashMap<String, String> paramMap = new HashMap<String, String>();
        //商户退款单号
        paramMap.put("outRefundNo","0111");
        //商户订单号
        paramMap.put("outTradeNo","0123");
        //微信退款单号
        paramMap.put("refundId","0234");
        //时间戳（验证参数签名是否过期时根据这个时间戳判断）
        paramMap.put("timestamp","123456585");
        //微信订单号
        paramMap.put("transactionId","0456");
        //微信支付标识(支付网关后台添加微信支付信息后生成)
        paramMap.put("wcpayType","YT");

        StringBuilder sb = new StringBuilder();
        List<String> paramNames = new ArrayList<String>(paramMap.size());

        //将需要加密的参数名放到集合中
        paramNames.addAll(paramMap.keySet());
        //将含有要加密的参数的参数名集合进行排序
        Collections.sort(paramNames);
        //根据排序好后的参数集合的值获取参数名（key）对应的值（value）
        for (String paramName : paramNames) {
            sb.append(paramName).append(paramMap.get(paramName));
        }

        //需要加密的字符串：outRefundNo0111outTradeNo0123refundId0234timestamp123456585transactionId0456wcpayTypeYT
        System.out.println("要加密的字符串："+sb.toString());

        //MD5加密
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] md5Digest = md.digest(sb.toString().getBytes("UTF-8"));
        StringBuilder sign = new StringBuilder();
        for (int i = 0; i < md5Digest.length; i++) {
            String hex = Integer.toHexString(md5Digest[i] & 0xFF);
            if (hex.length() == 1) {
                sign.append("0");
            }
            sign.append(hex.toUpperCase());
        }
        //加密后的字符串
        String appSign = sign.toString();
        System.out.println("加密串，appSign:"+appSign);

        //最后获取加密后的参数appSign的值
        //参数签名,BC722287E4C10518533DE7E3F2449A71
        paramMap.put("appSign",appSign);

    }

    public static HashMap<String, String> sign(Map<String, String> paramValues) {
        return sign(paramValues, null);
    }

    /**
     * @param paramValues
     * @param ignoreParamNames
     * @return
     */
    public static HashMap<String, String> sign(Map<String, String> paramValues,
                                               List<String> ignoreParamNames) {
        try {
            HashMap<String, String> signMap = new HashMap<String, String>();
            StringBuilder sb = new StringBuilder();
            List<String> paramNames = new ArrayList<String>(paramValues.size());
            paramNames.addAll(paramValues.keySet());
            if (ignoreParamNames != null && ignoreParamNames.size() > 0) {
                for (String ignoreParamName : ignoreParamNames) {
                    paramNames.remove(ignoreParamName);
                }
            }
            Collections.sort(paramNames);
            for (String paramName : paramNames) {
                sb.append(paramName).append(paramValues.get(paramName));
            }
            byte[] md5Digest = getMD5Digest(sb.toString());
            String sign = byte2hex(md5Digest);
            signMap.put("appParam", sb.toString());
            signMap.put("appSign", sign);
            return signMap;
        } catch (IOException e) {
            throw new RuntimeException("加密签名计算错误", e);
        }

    }

    public static String utf8Encoding(String value, String sourceCharsetName) {
        try {
            return new String(value.getBytes(sourceCharsetName), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e);
        }
    }

    private static byte[] getSHA1Digest(String data) throws IOException {
        byte[] bytes = null;
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            bytes = md.digest(data.getBytes("UTF-8"));
        } catch (GeneralSecurityException gse) {
            throw new IOException(gse);
        }
        return bytes;
    }

    private static byte[] getMD5Digest(String data) throws IOException {
        byte[] bytes = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            bytes = md.digest(data.getBytes("UTF-8"));
        } catch (GeneralSecurityException gse) {
            throw new IOException(gse);
        }
        return bytes;
    }


    private static String byte2hex(byte[] bytes) {
        StringBuilder sign = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() == 1) {
                sign.append("0");
            }
            sign.append(hex.toUpperCase());
        }
        return sign.toString();
    }


    public static String callService(String servicePath, List<NameValuePair> list , Integer socketTimeOut, Integer connectTimeout){
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String result = "";
        //设置超时时间
        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = new HttpPost(servicePath);
            //httpPost.addHeader("Content-Type", "text/html;charset=UTF-8");
            httpPost.setEntity(new UrlEncodedFormEntity(list, HTTP.UTF_8));
            if(socketTimeOut!=null&&connectTimeout!=null){
                RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeOut).
                        setConnectTimeout(connectTimeout).build();//设置请求和传输超时时间
                httpPost.setConfig(requestConfig);
            }
            response = httpclient.execute(httpPost);
            if(response.getStatusLine().getStatusCode()==200){
                HttpEntity entity = response.getEntity();
//			    InputStream s = entity.getContent();
                result = EntityUtils.toString(entity,"UTF-8");
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }


}
